﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace XNAFight.Engine.Inputs
{
    /// Donne l'état des inputs à chaque frame de façon statique
    class InputState : GameComponent
    {
        #region CHAMPS

        // Zone morte pour les sticks du pad
        private static float zone_morte;

        // Etat des inputs du clavier à la frame courante
        private static KeyboardState current_kbd_state;
        // Etat des inputs du clavier à la frame précédente
        private static KeyboardState last_kbd_state;
        
        // Etat des inputs du pad #1 à la frame courante
        private static GamePadState current_gpad_one_state;
        // Etat des inputs du pad #1 à la frame précédente
        private static GamePadState last_gpad_one_state;

        // Etat des inputs du pad #2 à la frame courante
        private static GamePadState current_gpad_two_state;
        // Etat des inputs du pad #2 à la frame précédente
        private static GamePadState last_gpad_two_state;

        // Etat des inputs du pad #3 à la frame courante
        private static GamePadState current_gpad_three_state;
        // Etat des inputs du pad #3 à la frame précédente
        private static GamePadState last_gpad_three_state;

        // Etat des inputs du pad #4 à la frame courante
        private static GamePadState current_gpad_four_state;
        // Etat des inputs du pad #4 à la frame précédente
        private static GamePadState last_gpad_four_state;

        #endregion
        
        #region INITIALISATION

        public InputState(Game _game) : base(_game)
        {
            zone_morte = 0.1f;

            current_kbd_state = new KeyboardState();
            last_kbd_state = new KeyboardState();

            current_gpad_one_state = new GamePadState();
            last_gpad_one_state = new GamePadState();

            current_gpad_two_state = new GamePadState();
            last_gpad_two_state = new GamePadState();

            current_gpad_three_state = new GamePadState();
            last_gpad_three_state = new GamePadState();

            current_gpad_four_state = new GamePadState();
            last_gpad_four_state = new GamePadState();
        }

        #endregion

        #region UPDATE
        public override void Update(GameTime _gameTime)
        {
            base.Update(_gameTime);
            last_kbd_state = current_kbd_state;
            current_kbd_state = Keyboard.GetState();

            last_gpad_one_state = current_gpad_one_state;
            current_gpad_one_state = GamePad.GetState(PlayerIndex.One);

            last_gpad_two_state = current_gpad_two_state;
            current_gpad_two_state = GamePad.GetState(PlayerIndex.Two);

            last_gpad_three_state = current_gpad_three_state;
            current_gpad_three_state = GamePad.GetState(PlayerIndex.Three);

            last_gpad_four_state = current_gpad_four_state;
            current_gpad_four_state = GamePad.GetState(PlayerIndex.Four);
        }
        #endregion

        #region METHODES CLAVIER

        // True si la touche _key est enfoncée
        public static bool isKeyPressed(Keys _key)
        {
            return (current_kbd_state.IsKeyDown(_key));
        }

        // True si la touche _key vient d'etre enfoncée
        public static bool isNewKeyPressed(Keys _key)
        {
            return (current_kbd_state.IsKeyDown(_key) &&
                    last_kbd_state.IsKeyUp(_key));
        }

        // True si la touche _key vient d'etre relachée
        public static bool isNewKeyReleased(Keys _key)
        {
            return (current_kbd_state.IsKeyUp(_key) &&
                    last_kbd_state.IsKeyDown(_key));
        }
        
        #endregion

        #region METHODES PAD

        // True si le bouton _btn est enfoncé
        public static bool isButtonPressed(Buttons _btn)
        {
            return 
                current_gpad_one_state.IsButtonDown(_btn) || 
                current_gpad_two_state.IsButtonDown(_btn) || 
                current_gpad_three_state.IsButtonDown(_btn) || 
                current_gpad_four_state.IsButtonDown(_btn);
        }

        // True si le bouton _btn est enfoncé
        public static bool isButtonPressed(Buttons _btn, PlayerIndex _player_index)
        {
            bool pressed = false;
            switch (_player_index)
            {
                case PlayerIndex.One: pressed = current_gpad_one_state.IsButtonDown(_btn);
                    break;
                case PlayerIndex.Two: pressed = current_gpad_two_state.IsButtonDown(_btn);
                    break;
                case PlayerIndex.Three: pressed = current_gpad_three_state.IsButtonDown(_btn);
                    break;
                case PlayerIndex.Four: pressed = current_gpad_four_state.IsButtonDown(_btn);
                    break;
            }
            return pressed;
        }

        // True si le bouton _btn vient d'etre enfoncé
        public static bool isNewButtonPressed(Buttons _btn)
        {
            return 
                (current_gpad_one_state.IsButtonDown(_btn) && last_gpad_one_state.IsButtonUp(_btn)) ||
                (current_gpad_two_state.IsButtonDown(_btn) && last_gpad_two_state.IsButtonUp(_btn)) ||
                (current_gpad_three_state.IsButtonDown(_btn) && last_gpad_three_state.IsButtonUp(_btn)) ||
                (current_gpad_four_state.IsButtonDown(_btn) && last_gpad_four_state.IsButtonUp(_btn));
        }

        // True si le bouton _btn vient d'etre enfoncé
        public static bool isNewButtonPressed(Buttons _btn, PlayerIndex _player_index)
        {
            bool pressed = false;
            switch (_player_index)
            {
                case PlayerIndex.One: pressed = current_gpad_one_state.IsButtonDown(_btn) && last_gpad_one_state.IsButtonUp(_btn);
                    break;
                case PlayerIndex.Two: pressed = current_gpad_two_state.IsButtonDown(_btn) && last_gpad_two_state.IsButtonUp(_btn);
                    break;
                case PlayerIndex.Three: pressed = current_gpad_three_state.IsButtonDown(_btn) && last_gpad_three_state.IsButtonUp(_btn);
                    break;
                case PlayerIndex.Four: pressed = current_gpad_four_state.IsButtonDown(_btn) && last_gpad_four_state.IsButtonUp(_btn);
                    break;
            }
            return pressed;
        }

        // True si le bouton _btn vient d'etre relaché
        public static bool isNewButtonReleased(Buttons _btn)
        {
            return false;
        }

        // True si le stick gauche est dirigé vers la gauche
        public static bool isLeftStickOnLeft(PlayerIndex _player_index)
        {
            bool on_left = false;

            switch (_player_index)
            {
                case PlayerIndex.One: on_left = current_gpad_one_state.ThumbSticks.Left.X < (-1f*zone_morte);
                    break;
                case PlayerIndex.Two: on_left = current_gpad_two_state.ThumbSticks.Left.X < (-1f * zone_morte);
                    break;
                case PlayerIndex.Three: on_left = current_gpad_three_state.ThumbSticks.Left.X < (-1f * zone_morte);
                    break;
                case PlayerIndex.Four: on_left = current_gpad_four_state.ThumbSticks.Left.X < (-1f * zone_morte);
                    break;
            }

            return on_left;
        }
        
        // True si le stick gauche est dirigé vers la gauche
        public static bool isLeftStickOnLeft()
        {
            return 
                (current_gpad_one_state.ThumbSticks.Left.X < (-1f * zone_morte)) ||
                (current_gpad_two_state.ThumbSticks.Left.X < (-1f * zone_morte)) ||
                (current_gpad_three_state.ThumbSticks.Left.X < (-1f * zone_morte)) ||
                (current_gpad_four_state.ThumbSticks.Left.X < (-1f * zone_morte)) ;

        }

        // True si le stick gauche est dirigé vers la droite
        public static bool isLeftStickOnRight(PlayerIndex _player_index)
        {
            bool on_right = false;

            switch (_player_index)
            {
                case PlayerIndex.One: on_right = current_gpad_one_state.ThumbSticks.Left.X > zone_morte;
                    break;
                case PlayerIndex.Two: on_right = current_gpad_two_state.ThumbSticks.Left.X > zone_morte;
                    break;
                case PlayerIndex.Three: on_right = current_gpad_three_state.ThumbSticks.Left.X > zone_morte;
                    break;
                case PlayerIndex.Four: on_right = current_gpad_four_state.ThumbSticks.Left.X > zone_morte;
                    break;
            }

            return on_right;
        }

        // True si le stick gauche est dirigé vers la droie
        public static bool isLeftStickOnRight()
        {
            return
                (current_gpad_one_state.ThumbSticks.Left.X > zone_morte) ||
                (current_gpad_two_state.ThumbSticks.Left.X > zone_morte) ||
                (current_gpad_three_state.ThumbSticks.Left.X > zone_morte) ||
                (current_gpad_four_state.ThumbSticks.Left.X > zone_morte);

        }

        // True si le stick gauche est dirigé vers le haut
        public static bool isLeftStickUpped(PlayerIndex _player_index)
        {
            bool upped = false;

            switch (_player_index)
            {
                case PlayerIndex.One: upped = current_gpad_one_state.ThumbSticks.Left.Y > zone_morte;
                    break;
                case PlayerIndex.Two: upped = current_gpad_two_state.ThumbSticks.Left.Y > zone_morte;
                    break;
                case PlayerIndex.Three: upped = current_gpad_three_state.ThumbSticks.Left.Y > zone_morte;
                    break;
                case PlayerIndex.Four: upped = current_gpad_four_state.ThumbSticks.Left.Y > zone_morte;
                    break;
            }

            return upped;
        }
        
        // True si le stick gauche est dirigé vers le haut
        public static bool isLeftStickUpped()
        {
            return
                (current_gpad_one_state.ThumbSticks.Left.Y > zone_morte) ||
                (current_gpad_two_state.ThumbSticks.Left.Y > zone_morte) ||
                (current_gpad_three_state.ThumbSticks.Left.Y > zone_morte) ||
                (current_gpad_four_state.ThumbSticks.Left.Y > zone_morte);

        }

        // True si le stick gauche est dirigé vers le bas
        public static bool isLeftStickDowned(PlayerIndex _player_index)
        {
            bool downed = false;

            switch (_player_index)
            {
                case PlayerIndex.One: downed = current_gpad_one_state.ThumbSticks.Left.Y < (-1f * zone_morte);
                    break;
                case PlayerIndex.Two: downed = current_gpad_two_state.ThumbSticks.Left.Y < (-1f * zone_morte);
                    break;
                case PlayerIndex.Three: downed = current_gpad_three_state.ThumbSticks.Left.Y < (-1f * zone_morte);
                    break;
                case PlayerIndex.Four: downed = current_gpad_four_state.ThumbSticks.Left.Y < (-1f * zone_morte);
                    break;
            }

            return downed;
        }

        // True si le stick gauche est dirigé vers le bas
        public static bool isLeftStickDowned()
        {
            return
                (current_gpad_one_state.ThumbSticks.Left.Y < (-1f * zone_morte)) ||
                (current_gpad_two_state.ThumbSticks.Left.Y < (-1f * zone_morte)) ||
                (current_gpad_three_state.ThumbSticks.Left.Y < (-1f * zone_morte)) ||
                (current_gpad_four_state.ThumbSticks.Left.Y < (-1f * zone_morte));

        }
        #endregion
    }
}
